package com.ruoyi.yl.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.redis.service.RedisService;
import com.ruoyi.common.domain.Activity;
import com.ruoyi.common.domain.constant.RedisKey;
import com.ruoyi.system.api.constant.YlStatus;
import com.ruoyi.common.domain.dto.MerchantActivityDTO;
import com.ruoyi.common.domain.query.MerchantActivityQuery;
import com.ruoyi.common.mapper.ActivityMapper;
import com.ruoyi.yl.service.IActivityService;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.executor.BatchResult;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 商家活动表，存储商家发布的霸王餐活动信息 服务实现类
 * </p>
 *
 * @author jiabao
 * @since 2025-06-25
 */
@Service
@Slf4j
public class ActivityServiceImpl extends ServiceImpl<ActivityMapper, Activity> implements IActivityService {

    
    @Resource 
    private RedisService redisService;

    @Override
    public List<Activity> selectActivityList(Activity activity) {
        Long merchantId = activity.getMerchantId();
        LambdaQueryWrapper<Activity> query = Wrappers.<Activity>lambdaQuery();
        query.eq(Activity::getStatus, YlStatus.NORMAL.getCode());
        query.eq(ObjectUtils.isNotEmpty(merchantId), Activity::getMerchantId, merchantId);
        query.orderByDesc(Activity::getCreatedAt);
        return this.getBaseMapper().selectList(query);
    }

    @Override
    public Activity selectActivityById(Long id) {
        return this.getBaseMapper().selectById(id);
    }

    @Override
    public int insertActivity(Activity activity) {
        return this.getBaseMapper().insert(activity);
    }

    @Override
    public int updateActivity(Activity activity) {
        return this.getBaseMapper().updateById(activity);
    }

    @Override
    public int deleteActivityByIds(Long[] ids) {
        List<Activity> list = this.getBaseMapper().selectByIds(CollectionUtils.toList(ids));
        list.forEach(e -> e.setStatus(YlStatus.ABNORMAL.getCode()));
        List<BatchResult> batchResults = this.getBaseMapper().updateById(list);
        return 1;
    }


    @Override
    public List<MerchantActivityDTO> getNearbyMerchantActivity(MerchantActivityQuery query) {

        // 这里可以做参数校验或者业务逻辑
        return this.getBaseMapper().selectMerchantActivity(query);
    }

    @Override
    public void preheatInventory() {
        log.info("PreheatInventory start");
        long sysStartTime = System.currentTimeMillis();
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime oneHourLater = now.minusHours(1);

        List<Activity> activityS = this.getBaseMapper().selectList(Wrappers.lambdaQuery(Activity.class)
                .eq(Activity::getStatus, YlStatus.NORMAL.getCode())
                .and(wrapper -> wrapper
                        // 已经开始但未结束
                        .le(Activity::getStartTime, now)
                        .ge(Activity::getEndTime, now)
                        .or()
                        // 或 预计1小时内开始
                        .gt(Activity::getStartTime, now)
                        .le(Activity::getStartTime, oneHourLater)
                )
        );

        //1. 查询出对应的活动
        //2. 将其满足要求的活动 id 和 持续时间 进行redis缓存。
        String key;
        for (Activity activity : activityS) {
            key = String.format(RedisKey.ACTIVITY_INVENTORY, activity.getId());
            if (!redisService.hasKey(key)) {
                //计算过期时间
                preheatInventoryByActivity(activity);
            }
        }
        log.info("PreheatInventory end 实际耗时ms:{}", System.currentTimeMillis() - sysStartTime);
    }


    @Override
    public void preheatInventoryByActivity(Activity activity) {
        String key = String.format(RedisKey.ACTIVITY_INVENTORY, activity.getId());
        LocalDateTime endTime = activity.getEndTime();
        LocalDateTime startTime = activity.getStartTime();
        Duration between = Duration.between(startTime, endTime);
        int remain = activity.getMaxParticipants() - activity.getCurrentParticipants();
         redisService.setCacheObject(key, remain,  between.getSeconds() + 3600, TimeUnit.SECONDS);
    }


    @Override
    public boolean verificationActivityHasStart(Long activityId) {
        String key = String.format(RedisKey.ACTIVITY_WHETHER_START, activityId);
        if (redisService.hasKey(key)) {
            //redis 已经有这个key啦直接返回 活动未开始 即可
            return false;
        }


        Activity activity = this.getBaseMapper().selectById(activityId);
        LocalDateTime startTime = activity.getStartTime();
        LocalDateTime endTime = activity.getEndTime();
        LocalDateTime now = LocalDateTime.now();


        boolean before = now.isBefore(startTime);
        boolean after = now.isAfter(endTime);
        if (before&&after) {
            //缓存redis 返回false 代表当前活动未开始。
            Duration between = Duration.between(LocalDateTime.now(), startTime);
            redisService.setCacheObject(key, activity,  between.getSeconds(), TimeUnit.SECONDS);
            return false;
        }

        //代表活动已经开始
        return true;


    }

    @Override
    public void RefundActivityNumber(Long activityId) {
        Activity activity = this.selectActivityById(activityId);
        activity.setCurrentParticipants( activity.getCurrentParticipants()-1);
        this.getBaseMapper().updateById(activity);
        preheatInventoryByActivity(activity);
    }
}
